package cn.smile.business.basic.impl;

import cn.smile.bean.dto.basic.ExpenseItemDTO;
import cn.smile.bean.dto.basic.MyShopDTO;
import cn.smile.bean.dto.basic.VoucherDTO;
import cn.smile.bean.dto.basic.VoucherMemberDTO;
import cn.smile.bean.dto.core.SysUserDTO;
import cn.smile.bean.entity.basic.VoucherMember;
import cn.smile.bean.form.basic.item.QueryItemForm;
import cn.smile.bean.form.basic.voucher.AddVoucherMemberForm;
import cn.smile.bean.form.basic.voucher.QueryVouMemForm;
import cn.smile.bean.form.core.user.QueryUserForm;
import cn.smile.business.basic.*;
import cn.smile.business.core.ISysUserService;
import cn.smile.commons.constant.NumberConstant;
import cn.smile.commons.domain.BaseServiceImpl;
import cn.smile.commons.enums.basic.VoucherStatusEnum;
import cn.smile.repository.basic.VoucherMemberMapper;
import cn.smile.utils.BeanCopy;
import cn.smile.utils.DateFormatUtil;
import cn.smile.utils.UserUtil;
import cn.smile.utils.VoucherUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class VoucherMemberServiceImpl extends BaseServiceImpl<VoucherMemberMapper, VoucherMember> implements IVoucherMemberService {

    @Resource
    private IVoucherService voucherService;
    @Resource
    private IMyShopService shopService;
    @Resource
    private IVoucherItemService voucherItemService;
    @Resource
    private IExpenseItemService itemService;
    @Resource
    private ISysUserService userService;

    @Override
    public Boolean addInfo(AddVoucherMemberForm form) {
        log.info("[VoucherMemberServiceImpl].[addInfo] ------> 会员新增代金券 Start, form = {}", JSON.toJSONString(form));
        VoucherDTO voucher = voucherService.getVoucherById(form.getVoucherId());
        VoucherMember entity = BeanCopy.copyBean(voucher, VoucherMember.class);
        //置空ID,重新生成
        entity.setId(null);
        entity.setVoucherId(voucher.getId());
        entity.setMemberId(form.getMemberId());
        entity.setTopUpId(form.getTopUpId());
        entity.setIssueUser(UserUtil.getUserInfo().getId());
        entity.setIssueTime(LocalDateTime.now());
        entity.setVoucherStatus(VoucherUtil.getStatusByMember(voucher.getValidityStart(), voucher.getValidityEnd(), null).getSn());
        boolean flag = super.create(entity);
        log.info("[VoucherMemberServiceImpl].[addInfo] ------> 会员新增代金券 End, flag = {}", flag);
        return flag;
    }

    @Override
    public IPage<VoucherMemberDTO> getPage(QueryVouMemForm form) {
        log.info("[VoucherMemberServiceImpl].[getPage] ------> 分页查询和会员代金券 Start, form = {}", JSON.toJSONString(form));
        Page<VoucherMember> basePage = baseMapper.selectPage(form.queryPage(), this.getQueryParams(form));
        IPage<VoucherMemberDTO> dataPage = BeanCopy.copyPage(basePage, VoucherMemberDTO.class);
        this.setDetail(dataPage.getRecords());
        log.info("[VoucherMemberServiceImpl].[getPage] ------> 分页查询和会员代金券 End");
        return dataPage;
    }

    @Override
    public List<VoucherMemberDTO> getList(QueryVouMemForm form) {
        log.info("[VoucherMemberServiceImpl].[getList] ------> 列表查询会员代金券列表 Start, form = {}", JSON.toJSONString(form));
        List<VoucherMember> baseList = baseMapper.selectList(this.getQueryParams(form));
        List<VoucherMemberDTO> dataList = BeanCopy.copyList(baseList, VoucherMemberDTO.class);
        this.setDetail(dataList);
        log.info("[VoucherMemberServiceImpl].[getList] ------> 列表查询会员代金券列表 Start, form = {}", JSON.toJSONString(form));
        return dataList;
    }

    @Override
    public void updateStatus() {
        log.info("[VoucherMemberServiceImpl].[updateStatus] ------> 更新全部会员代金券状态 Start");
        QueryVouMemForm form = new QueryVouMemForm();
        form.setUseShopFlag(Boolean.FALSE);
        form.setVoucherStatusList(Lists.newArrayList(VoucherStatusEnum.NOT_ACTIVATED.getSn(), VoucherStatusEnum.IN_EFFECT.getSn(), VoucherStatusEnum.UN_USE.getSn()));
        List<VoucherMemberDTO> dataList = this.getList(form);
        if (!CollectionUtils.isEmpty(dataList)) {
            for (VoucherMemberDTO dto : dataList) {
                dto.setVoucherStatus(VoucherUtil.getStatusByMember(dto.getValidityStart(), dto.getValidityEnd(), dto.getUseTime()).getSn());
                super.update(dto);
            }
        }
        log.info("[VoucherMemberServiceImpl].[updateStatus] ------> 更新全部会员代金券状态 End");
    }

    @Override
    public Map<String, Integer> countIssueNum(List<String> voucherIds) {
        log.info("[VoucherMemberServiceImpl].[countIssueNum] ------> 统计代金券下发数量 Start");
        Map<String, Integer> dataMap = Maps.newHashMap();
        if (!CollectionUtils.isEmpty(voucherIds)) {
            List<VoucherMember> dataList = baseMapper.selectList(new QueryWrapper<VoucherMember>().lambda().eq(VoucherMember::getDeleted, Boolean.FALSE).in(VoucherMember::getVoucherId, voucherIds));
            if (!CollectionUtils.isEmpty(dataList)) {
                for (VoucherMember entity : dataList) {
                    if (!dataMap.containsKey(entity.getVoucherId())) {
                        dataMap.put(entity.getVoucherId(), NumberConstant.ZERO);
                    }
                    dataMap.put(entity.getVoucherId(), dataMap.get(entity.getVoucherId()) + NumberConstant.ONE);
                }
            }
        }
        log.info("[VoucherMemberServiceImpl].[countIssueNum] ------> 统计代金券下发数量 End");
        return dataMap;
    }

    @Override
    public Map<String, Integer> countNumByMember(List<String> memberIds) {
        log.info("[VoucherMemberServiceImpl].[countNumByMember] ------> 统计会员代金券数量 Start");
        Map<String, Integer> dataMap = Maps.newHashMap();
        if (!CollectionUtils.isEmpty(memberIds)) {
            List<VoucherMember> dataList = baseMapper.selectList(new QueryWrapper<VoucherMember>().lambda().eq(VoucherMember::getDeleted, Boolean.FALSE).in(VoucherMember::getMemberId, memberIds).in(VoucherMember::getVoucherStatus, Lists.newArrayList(VoucherStatusEnum.UN_USE.getSn())));
            if (!CollectionUtils.isEmpty(dataList)) {
                for (VoucherMember entity : dataList) {
                    if (!dataMap.containsKey(entity.getMemberId())) {
                        dataMap.put(entity.getMemberId(), NumberConstant.ZERO);
                    }
                    dataMap.put(entity.getMemberId(), dataMap.get(entity.getMemberId()) + NumberConstant.ONE);
                }
            }
        }
        log.info("[VoucherMemberServiceImpl].[countNumByMember] ------> 统计会员代金券数量 End");
        return dataMap;
    }

    @Override
    public Integer usableNum(String memberId, String itemId) {
        log.info("[VoucherMemberServiceImpl].[usableNum] ------> 查询会员指定项目可用代金券数量 Start, memberId = {}, itemId = {}", memberId, itemId);
        int usableNum = NumberConstant.ZERO;
        QueryVouMemForm form = new QueryVouMemForm();
        form.setMemberId(memberId);
        form.setItemIdList(Lists.newArrayList(itemId));
        form.setVoucherStatusList(Lists.newArrayList(VoucherStatusEnum.UN_USE.getSn(), VoucherStatusEnum.IN_EFFECT.getSn()));
        List<VoucherMemberDTO> voucherList = this.getList(form);
        if (!CollectionUtils.isEmpty(voucherList)) {
            usableNum = voucherList.size();
        }
        log.info("[VoucherMemberServiceImpl].[usableNum] ------> 查询会员指定项目可用代金券数量 End, usableNum = {}", usableNum);
        return usableNum;
    }

    @Override
    public VoucherMemberDTO getInfoById(String id) {
        log.info("[VoucherMemberServiceImpl].[getInfoById] ------> 代金券ID查询代金券信息 Start, id = {}", id);
        VoucherMember base = super.get(id);
        VoucherMemberDTO entity = BeanCopy.copyBean(base, VoucherMemberDTO.class);
        this.setDetail(Lists.newArrayList(entity));
        log.info("[VoucherMemberServiceImpl].[getInfoById] ------> 代金券ID查询代金券信息 End");
        return entity;
    }

    @Override
    public Boolean updateVoucherStatus(String id, VoucherStatusEnum status) {
        log.info("[VoucherMemberServiceImpl].[getInfoById] ------> 更新代金券状态 Start, id = {}", id);
        VoucherMemberDTO entity = this.getInfoById(id);
        entity.setVoucherStatus(status.getSn());
        entity.setUseTime(LocalDateTime.now());
        if (status == VoucherStatusEnum.UN_USE) {
            entity.setVoucherStatus(VoucherUtil.getStatusByMember(entity.getValidityStart(), entity.getValidityEnd(), entity.getUseTime()).getSn());
            entity.setUseTime(null);
        }
        boolean flag = super.update(entity);
        log.info("[VoucherMemberServiceImpl].[getInfoById] ------> 更新代金券状态 End, flag = {}", flag);
        return flag;
    }

    @Override
    public void delByTopUpId(String topUpId) {
        log.info("[VoucherMemberServiceImpl].[delByTopUpId] ------> 根据充值记录ID删除代金券信息 Start, topUpId = {}", topUpId);
        List<VoucherMember> baseList = baseMapper.selectList(new QueryWrapper<VoucherMember>().lambda().eq(VoucherMember::getTopUpId, topUpId).eq(VoucherMember::getDeleted, Boolean.FALSE));
        if (!CollectionUtils.isEmpty(baseList)) {
            for (VoucherMember base : baseList) {
                super.delById(base.getId());
            }
        }
        log.info("[VoucherMemberServiceImpl].[delByTopUpId] ------> 根据充值记录ID删除代金券信息 End");
    }

    @Override
    public Map<String, Integer> countNumByTopUpIds(List<String> topUpIds) {
        log.info("[VoucherMemberServiceImpl].[countNumByTopUpIds] ------> 根据充值记录ID集合统计代金券数量 Start");
        Map<String, Integer> countMap = Maps.newHashMap();
        if (!CollectionUtils.isEmpty(topUpIds)) {
            List<VoucherMember> baseList = baseMapper.selectList(new QueryWrapper<VoucherMember>().lambda().in(VoucherMember::getTopUpId, topUpIds).eq(VoucherMember::getDeleted, Boolean.FALSE));
            if (!CollectionUtils.isEmpty(baseList)) {
                for (VoucherMember base : baseList) {
                    if (!countMap.containsKey(base.getTopUpId())) {
                        countMap.put(base.getTopUpId(), NumberConstant.ZERO);
                    }
                    countMap.put(base.getTopUpId(), countMap.get(base.getTopUpId()) + NumberConstant.ONE);
                }
            }
        }
        log.info("[VoucherMemberServiceImpl].[countNumByTopUpIds] ------> 根据充值记录ID集合统计代金券数量 End");
        return countMap;
    }

    @Override
    public Integer countSendVouMemNum(String timeStart, String timeEnd) {
        log.info("[VoucherMemberServiceImpl].[countSendVouMemNum] ------> 统计会员代金券发放数量 Start, timeStart = {}, timeEnd = {}", timeStart, timeEnd);
        Integer countNum = this.countVouMemNum(timeStart, timeEnd, Boolean.TRUE);
        log.info("[VoucherMemberServiceImpl].[countSendVouMemNum] ------> 统计会员代金券发放数量 End, countNum = {}", countNum);
        return countNum;
    }

    @Override
    public Integer countUseVouMemNum(String timeStart, String timeEnd) {
        log.info("[VoucherMemberServiceImpl].[countUseVouMemNum] ------> 统计会员代金券使用数量 Start, timeStart = {}, timeEnd = {}", timeStart, timeEnd);
        Integer countNum = this.countVouMemNum(timeStart, timeEnd, Boolean.FALSE);
        log.info("[VoucherMemberServiceImpl].[countUseVouMemNum] ------> 统计会员代金券使用数量 End, countNum = {}", countNum);
        return countNum;
    }

    /**
     * 按标记统计会员代金券数量
     *
     * @param timeStart 统计开始时间
     * @param timeEnd   统计结束时间
     * @param countFlag 统计标记(true-发放量, false-使用量)
     * @return 统计结果
     */
    private Integer countVouMemNum(String timeStart, String timeEnd, Boolean countFlag) {
        MyShopDTO shop = shopService.getMyShop();
        LambdaQueryWrapper<VoucherMember> qw = new QueryWrapper<VoucherMember>().lambda().eq(VoucherMember::getDeleted, Boolean.FALSE);
        qw.eq(VoucherMember::getShopId, shop.getId());
        if (countFlag) {
            qw.ge(VoucherMember::getIssueTime, timeStart);
            qw.le(VoucherMember::getIssueTime, timeEnd);
        } else {
            qw.ge(VoucherMember::getUseTime, timeStart);
            qw.le(VoucherMember::getUseTime, timeEnd);
        }
        Long countNum = baseMapper.selectCount(qw);
        if (ObjectUtils.isEmpty(countNum)) {
            countNum = NumberConstant.ZERO_LONG;
        }
        return Integer.valueOf(countNum.toString());
    }

    /**
     * 写入代金券详细信息
     *
     * @param dataList 代金券列表
     */
    private void setDetail(List<VoucherMemberDTO> dataList) {
        if (!CollectionUtils.isEmpty(dataList)) {
            List<String> vouIds = Lists.newArrayList();
            dataList.forEach(data -> vouIds.add(data.getVoucherId()));
            Map<String, SysUserDTO> userMap = userService.getMyShopUserMap(new QueryUserForm());
            Map<String, List<String>> itemIdsMap = voucherItemService.getItemIdsMap(vouIds);
            Map<String, ExpenseItemDTO> itemMap = itemService.getItemMap(new QueryItemForm());
            for (VoucherMemberDTO entity : dataList) {
                entity.setVoucherStatusName(VoucherStatusEnum.get(entity.getVoucherStatus()).getMsg());
                entity.setValidityDate(String.format("%s - %s", DateFormatUtil.parseDateToStr(DateFormatUtil.localDateToDate(entity.getValidityStart()), DateFormatUtil.DATE_TIME_FORMAT_7), DateFormatUtil.parseDateToStr(DateFormatUtil.localDateToDate(entity.getValidityEnd()), DateFormatUtil.DATE_TIME_FORMAT_7)));
                entity.setIssueUserName(userMap.getOrDefault(entity.getIssueUser(), new SysUserDTO()).getNickName());
                if (itemIdsMap.containsKey(entity.getVoucherId())) {
                    List<String> itemList = itemIdsMap.get(entity.getVoucherId());
                    entity.setItemList(itemList);
                    entity.setItemNames(VoucherUtil.getItemNames(itemList, itemMap));
                }
            }
        }
    }

    /**
     * 组装查询参数
     *
     * @param form 查询参数对象
     * @return 数据库查询对象
     */
    private LambdaQueryWrapper<VoucherMember> getQueryParams(QueryVouMemForm form) {
        LambdaQueryWrapper<VoucherMember> qw = new QueryWrapper<VoucherMember>().lambda().eq(VoucherMember::getDeleted, Boolean.FALSE);
        if (form.getUseShopFlag()) {
            MyShopDTO shop = shopService.getMyShop();
            qw.eq(VoucherMember::getShopId, shop.getId());
        }
        if (!ObjectUtils.isEmpty(form.getMemberId())) {
            qw.eq(VoucherMember::getMemberId, form.getMemberId());
        }
        if (!ObjectUtils.isEmpty(form.getVoucherId())) {
            qw.eq(VoucherMember::getVoucherId, form.getVoucherId());
        }
        if (!ObjectUtils.isEmpty(form.getVoucherName())) {
            qw.like(VoucherMember::getVoucherName, form.getVoucherName());
        }
        if (!CollectionUtils.isEmpty(form.getVoucherStatusList())) {
            qw.in(VoucherMember::getVoucherStatus, form.getVoucherStatusList());
        }
        if (!CollectionUtils.isEmpty(form.getItemIdList())) {
            List<String> voucherIds = voucherItemService.getVoucherIdByItemList(form.getItemIdList());
            qw.in(VoucherMember::getVoucherId, voucherIds);
        }
        return qw;
    }
}
